package com.bayss.core.service;

import com.bayss.core.constant.ResultMsg;
import com.bayss.core.entity.rbac.*;
import com.bayss.core.entity.rbac.mapper.*;
import com.bayss.core.entity.rbac.query.AdminQuery;
import com.bayss.core.model.UserInfoVo;
import com.bayss.core.service.user.ObgUserService;
import com.bayss.core.util.FileUtil;
import com.bayss.core.util.TokenUtils;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class RbacService {
    @Autowired
    private OBGRoleInfoMapper roleInfoMapper;
    @Autowired
    private OBGUserInfoMapper userInfoMapper;
    @Autowired
    private ObgUserService obgUserService;
    @Autowired
    private PermissionsService permissionsService;
    @Autowired
    private OBGRolePermissionMapper rolePermissionMapper;
    @Autowired
    private OBGUserRoleMapper userRoleMapper;


    public ResultMsg resetPassword(Integer userId, String passwordOld, String passwordNew, String passowordNew2) {
        if (StringUtils.isEmpty(passwordOld)
                || StringUtils.isEmpty(passwordNew)
                || StringUtils.isEmpty(passowordNew2)) {
            return ResultMsg.fail(-1, "密码不能空");
        }
        if (!passowordNew2.equals(passwordNew)) {
            return ResultMsg.fail(-1, "两次新密码不一致");
        }
        OBGUserInfo userInfo = userInfoMapper.selectByPrimaryKey(userId);
        if (!passwordOld.equals(userInfo.getPassword())) {
            return ResultMsg.fail(-1, "旧密码不正确");
        }
        userInfo.setPassword(passwordNew);
        userInfoMapper.updateByPrimaryKeySelective(userInfo);
        return ResultMsg.success();
    }

    @Transactional
    public ResultMsg editUser(UserInfoVo userInfoVo) {
        OBGUserInfo obgUserInfo = new OBGUserInfo();
        BeanUtils.copyProperties(userInfoVo, obgUserInfo);
        obgUserInfo.setHeadPortraitUrl(FileUtil.formatImgUrl(userInfoVo.getHeadPortraitUrl()));
        userInfoMapper.updateByPrimaryKeySelective(obgUserInfo);

        if (userInfoVo.getRoleIds() != null && userInfoVo.getRoleIds().size() > 0) {
            OBGUserRoleExample userRoleExample = new OBGUserRoleExample();
            userRoleExample.createCriteria().andUidEqualTo(userInfoVo.getId());
            userRoleMapper.deleteByExample(userRoleExample);

            //添加角色
            addUserRole(obgUserInfo.getAccount(), userInfoVo.getRoleIds());
        }
        return ResultMsg.success();
    }

    /**
     * 登录
     *
     * @param account
     * @param password
     * @return
     */
    public OBGUserInfo loginAdmin(String account, String password, int outHours) {
        OBGUserInfo userInfo = obgUserService.findByAccount(account, password);
        if (userInfo == null) {
            return null;
        }
        String token = TokenUtils.createToken("user_id", userInfo.getId(), outHours);
        userInfo.setToken(token);
        return userInfo;
    }

    public List<OBGRoleInfo> findRolesByUser(Integer uid) {
        OBGUserRoleExample example = new OBGUserRoleExample();
        OBGUserRoleExample.Criteria criteria = example.createCriteria();
        criteria.andUidEqualTo(uid);
        List<OBGUserRole> list = userRoleMapper.selectByExample(example);
        List<Integer> roleIdList = list.stream().map(OBGUserRole::getRoleId).collect(Collectors.toList());
        if (roleIdList.size() == 0) {
            return new ArrayList<>();
        }
        //roleLst
        OBGRoleInfoExample roleInfoExample = new OBGRoleInfoExample();
        roleInfoExample.createCriteria().andIdIn(roleIdList);
        List<OBGRoleInfo> roleList = roleInfoMapper.selectByExample(roleInfoExample);
        for (OBGRoleInfo r : roleList) {
            r.setPermissionIds(this.findPermIdsByRoleId(r.getId()));
        }
        return roleList;
    }

    public PageInfo<OBGUserInfo> listAdmin(AdminQuery adminQuery) {
        PageInfo<OBGUserInfo> result = obgUserService.findPage(adminQuery);

        //带上角色信息
        for (OBGUserInfo userInfo : result.getList()) {
            userInfo.setRoleInfoList(findRolesByUser(userInfo.getId()));
        }
        return result;
    }

    @Transactional
    public ResultMsg addAdmin(UserInfoVo userInfoVo) {
        OBGUserInfoExample example = new OBGUserInfoExample();
        example.createCriteria().andAccountEqualTo(userInfoVo.getAccount());
        List<OBGUserInfo> list = userInfoMapper.selectByExample(example);
        if (list != null && list.size() > 0) {
            return ResultMsg.fail(-1, "account已存在");
        }

        OBGUserInfo obgUserInfo = new OBGUserInfo();
        BeanUtils.copyProperties(userInfoVo, obgUserInfo);
        obgUserInfo.setStatus(1);
        obgUserInfo.setCreateTime(new Date());
        obgUserInfo.setHeadPortraitUrl(FileUtil.formatImgUrl(userInfoVo.getHeadPortraitUrl()));
        userInfoMapper.insertSelective(obgUserInfo);

        System.out.println(userInfoVo.getId());

        if (userInfoVo.getRoleIds() != null) {
            addUserRole(obgUserInfo.getAccount(), userInfoVo.getRoleIds());
        }
        return ResultMsg.success();
    }

    public void addUserRole(String account, List<Integer> roleIds) {
        OBGUserInfoExample example = new OBGUserInfoExample();
        example.createCriteria().andAccountEqualTo(account);
        List<OBGUserInfo> userInfoList = userInfoMapper.selectByExample(example);

        for (Integer roleId : roleIds) {
            OBGUserRole userRole = new OBGUserRole();
            userRole.setRoleId(roleId);
            userRole.setUid(userInfoList.get(0).getId());
            userRoleMapper.insertSelective(userRole);
        }
    }

    @Transactional
    public void delAdmin(Integer uid) {
        //删除用户角色关系
        OBGUserRoleExample userRoleExample = new OBGUserRoleExample();
        OBGUserRoleExample.Criteria userRoleExampleCriteria = userRoleExample.createCriteria();
        userRoleExampleCriteria.andUidEqualTo(uid);
        userRoleMapper.deleteByExample(userRoleExample);

        //删除用户
        userInfoMapper.deleteByPrimaryKey(uid);
    }

    public void adminStatus(Integer uid, Integer status) {
        OBGUserInfo userInfo = new OBGUserInfo();
        userInfo.setId(uid);
        userInfo.setStatus(status);
        userInfoMapper.updateByPrimaryKeySelective(userInfo);
    }

    public List<OBGRoleInfo> listRole() {
        OBGRoleInfoExample example = new OBGRoleInfoExample();
        List<OBGRoleInfo> obgRoleInfos = roleInfoMapper.selectByExample(example);

        List<Integer> userIdList = obgRoleInfos.stream().map(OBGRoleInfo::getOperatorId).collect(Collectors.toList());
        List<OBGUserInfo> userList = obgUserService.findByIdList(userIdList);
        Map<Integer, OBGUserInfo> map = userList.stream().collect(Collectors.toMap(OBGUserInfo::getId, userInfo -> userInfo));
        for (OBGRoleInfo r : obgRoleInfos) {
            OBGUserInfo obgUserInfo = map.get(r.getOperatorId());
            r.setOperatorName(obgUserInfo == null ? "" : obgUserInfo.getNickname());
        }
        return obgRoleInfos;
    }

    public PageInfo<OBGRoleInfo> findRolesByPage(Integer page, Integer size) {
        OBGRoleInfoExample example = new OBGRoleInfoExample();
        example.setOrderByClause("create_time desc");
        PageInfo<OBGRoleInfo> result = PageHelper.startPage(page, size).doSelectPageInfo(() -> roleInfoMapper.selectByExample(example));

        for (OBGRoleInfo r : result.getList()) {
            r.setPermissionIds(this.findPermIdsByRoleId(r.getId()));
            OBGUserInfo userInfo = obgUserService.getUser(r.getOperatorId());
            r.setOperatorName(userInfo == null ? "" : userInfo.getNickname());
        }
        return result;
    }

    //查询角色下的权限ids
    private List<Integer> findPermIdsByRoleId(Integer roleId) {
        OBGRolePermissionExample rolePermiExample = new OBGRolePermissionExample();
        rolePermiExample.createCriteria().andRoleIdEqualTo(roleId);
        List<OBGRolePermission> rpList = rolePermissionMapper.selectByExample(rolePermiExample);
        List<Integer> permIdList = rpList.stream().map(OBGRolePermission::getPermissionId).collect(Collectors.toList());
        return permIdList;
    }

    public void addRole(OBGRoleInfo roleInfo, List<Integer> permissionIds) {
        int i = roleInfoMapper.insertSelective(roleInfo);
        if (!CollectionUtils.isEmpty(permissionIds)) {
            permissionIds.forEach(pid -> {
                OBGRolePermission rolePermission = new OBGRolePermission();
                rolePermission.setRoleId(roleInfo.getId());
                rolePermission.setPermissionId(pid);
                rolePermissionMapper.insert(rolePermission);
            });
        }
    }

    public void updateRole(OBGRoleInfo roleInfo, List<Integer> permissionIds) {
        roleInfoMapper.updateByPrimaryKeySelective(roleInfo);

        if (!CollectionUtils.isEmpty(permissionIds)) {
            OBGRolePermissionExample example = new OBGRolePermissionExample();
            example.createCriteria().andRoleIdEqualTo(roleInfo.getId());
            rolePermissionMapper.deleteByExample(example);

            permissionIds.forEach(pid -> {
                OBGRolePermission rolePermission = new OBGRolePermission();
                rolePermission.setRoleId(roleInfo.getId());
                rolePermission.setPermissionId(pid);
                rolePermissionMapper.insert(rolePermission);
            });
        }
    }

    public void delRole(Integer roleId) {
        //删除角色权限对应关系
        OBGRolePermissionExample example = new OBGRolePermissionExample();
        OBGRolePermissionExample.Criteria criteria = example.createCriteria();
        criteria.andRoleIdEqualTo(roleId);
        rolePermissionMapper.deleteByExample(example);
        //删除角色
        roleInfoMapper.deleteByPrimaryKey(roleId);
    }

    public void roleStatus(Integer roleId, Integer status) {
        OBGRoleInfo roleInfo = new OBGRoleInfo();
        roleInfo.setId(roleId);
        roleInfo.setStatus(status);
        roleInfoMapper.updateByPrimaryKeySelective(roleInfo);
    }

    /**
     * 返回权限树结构
     *
     * @param roleId
     * @param userId
     * @return
     */
    public List<OBGPermissionsInfo> treePermission(Integer roleId, Integer userId) {
        List<OBGPermissionsInfo> all = this.listPermission(roleId, userId);
        List<OBGPermissionsInfo> parent0List = filterByParentId(all, 0);

        for (OBGPermissionsInfo p : parent0List) {
            p.setList(getChildren(p.getId(), all));
        }
        return parent0List;
    }

    /**
     * 查询角色或用户的权限集合
     * @param roleId
     * @param userId
     * @return
     */
    public List<OBGPermissionsInfo> listPermission(Integer roleId, Integer userId) {
        List<Integer> roleIds = new ArrayList<>();
        OBGRolePermissionExample rolePermissionExample = new OBGRolePermissionExample();
        OBGRolePermissionExample.Criteria rolePermissionExampleCriteria = rolePermissionExample.createCriteria();
        if (roleId != null) {
            roleIds.add(roleId);
        }
        if (userId != null) {
            OBGUserRoleExample userRoleExample = new OBGUserRoleExample();
            OBGUserRoleExample.Criteria userRoleCriteria = userRoleExample.createCriteria();
            userRoleCriteria.andUidEqualTo(userId);
            List<OBGUserRole> list = userRoleMapper.selectByExample(userRoleExample);
            roleIds.addAll(list.stream().map(OBGUserRole::getRoleId).collect(Collectors.toList()));
        }

        if (roleIds.size() > 0) {
            rolePermissionExampleCriteria.andRoleIdIn(roleIds);
        }

        if (roleIds.size() == 0) {
            //查询全部
            return permissionsService.findAll();
        }

        //根据查角色权限list
        List<OBGRolePermission> obgRolePermissions = rolePermissionMapper.selectByExample(rolePermissionExample);
        List<Integer> permissionIds = obgRolePermissions.stream().map(e -> e.getPermissionId()).collect(Collectors.toList());

        //查权限list
        return permissionsService.findByIdList(permissionIds);
    }

    public ResultMsg addOBGPermissionsInfo(OBGPermissionsInfo obgPermissionsInfo) {
        if (obgPermissionsInfo.getType() == null) {
            return ResultMsg.fail(-1, "权限类型type不能为空");
        }
        if (obgPermissionsInfo.getType() != 0 && obgPermissionsInfo.getParentId() == null) {
            return ResultMsg.fail(-1, "父级id不能为空");
        }
        if (obgPermissionsInfo.getName() == null) {
            return ResultMsg.fail(-1, "名称不能为空");
        }
        if (obgPermissionsInfo.getType() == 1 && obgPermissionsInfo.getUrl() == null) {
            return ResultMsg.fail(-1, "url不能为空");
        }
        if (obgPermissionsInfo.getType() == 0) {
            obgPermissionsInfo.setParentId(0);
        }
        obgPermissionsInfo.setCreateTime(new Date());
        obgPermissionsInfo.setStatus(Byte.valueOf("1"));
        permissionsService.save(obgPermissionsInfo);
        return ResultMsg.success();
    }

    public void updateOBGPermissionsInfo(OBGPermissionsInfo obgPermissionsInfo) {
        permissionsService.updateOBGPermissionsInfo(obgPermissionsInfo);
    }


    public ResultMsg deleteOBGPermissionsInfoAndChildren(Integer id) {
        List<OBGPermissionsInfo> all = new ArrayList<>();

        OBGPermissionsInfo obgPermissionsInfo = permissionsService.findById(id);
        all.add(obgPermissionsInfo);

        List<OBGPermissionsInfo> list1 = permissionsService.findChildrenById(id);
        all.addAll(list1);

        for (OBGPermissionsInfo p1 : list1) {
            List<OBGPermissionsInfo> list2 = permissionsService.findChildrenById(p1.getId());
            all.addAll(list2);
        }
        List<Integer> ids = all.stream().map(e -> e.getId()).collect(Collectors.toList());

        //检查权限是否已经被角色关联
        OBGRolePermissionExample rolePermissionExample = new OBGRolePermissionExample();
        rolePermissionExample.createCriteria().andPermissionIdIn(ids);
        List<OBGRolePermission> rolePlist = rolePermissionMapper.selectByExample(rolePermissionExample);
        if (rolePlist != null && rolePlist.size() > 0) {
            return ResultMsg.fail(250, "当前权限已被角色关联，请先解除角色与权限关联关系");
        }

        //删除权限
        permissionsService.deleteByIds(ids);
        return ResultMsg.success();
    }


    /**
     * 判断用户是否拥有url权限
     */
    public boolean checkUserPermission(Integer userId, String url) {
        OBGPermissionsInfo currPerm = permissionsService.findPermissionsByUrl(url);
        if (currPerm == null) {
            return false;
        }
        //权限：1目录权限，2菜单权限，3按钮权限
        List<OBGPermissionsInfo> userPermList = listPermission(null, userId);
        if (userPermList.contains(currPerm)) {
            return true;
        }

        //当前url没有权限时，向上查找
        boolean result = permissionsService.checkParent(userPermList, currPerm.getParentId());
        return result;
    }


    /**
     * 递归查询当前权限下及子级
     */
    public List<OBGPermissionsInfo> getChildren(Integer id, List<OBGPermissionsInfo> all) {
        List<OBGPermissionsInfo> treeMenu = filterByParentId(all, id);
        for (OBGPermissionsInfo menu : treeMenu) {
            menu.setList(getChildren(menu.getId(), all));
        }
        return treeMenu;
    }


    private List<OBGPermissionsInfo> filterByParentId(List<OBGPermissionsInfo> all, Integer parentId) {
        List<OBGPermissionsInfo> list = all.stream().filter(p -> p.getParentId().equals(parentId)).collect(Collectors.toList());
        return list;
    }

}
